// Copyright (c) 2023 - 2025 IBM Corp.
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package reader provides the Reader monad implementation for functional programming in Go.
//
// The Reader monad is used to pass a shared environment or configuration through a computation
// without explicitly threading it through every function call. It represents a computation that
// depends on some external context of type R and produces a value of type A.
//
// # Core Concept
//
// A Reader[R, A] is simply a function from R to A: func(R) A
// - R is the environment/context type (read-only)
// - A is the result type
//
// # Key Benefits
//
//   - Dependency Injection: Pass configuration or dependencies implicitly
//   - Composition: Combine readers that share the same environment
//   - Testability: Easy to test by providing different environments
//   - Avoid Threading: No need to pass context through every function
//
// # Basic Usage
//
//	// Define a configuration type
//	type Config struct {
//	    Host string
//	    Port int
//	}
//
//	// Create readers that depend on Config
//	getHost := reader.Asks(func(c Config) string { return c.Host })
//	getPort := reader.Asks(func(c Config) int { return c.Port })
//
//	// Compose readers
//	getURL := reader.Map(func(host string) string {
//	    return "http://" + host
//	})(getHost)
//
//	// Run the reader with a config
//	config := Config{Host: "localhost", Port: 8080}
//	url := getURL(config) // "http://localhost"
//
// # Common Operations
//
//   - Ask: Get the current environment
//   - Asks: Project a value from the environment
//   - Map: Transform the result value
//   - Chain: Sequence computations that depend on previous results
//   - Local: Modify the environment for a sub-computation
//
// # Monadic Operations
//
// The Reader type implements the Functor, Applicative, and Monad type classes:
//
//   - Functor: Map over the result value
//   - Applicative: Combine multiple readers with independent computations
//   - Monad: Chain readers where later computations depend on earlier results
//
// # Related Packages
//
//   - reader/generic: Generic implementations for custom reader types
//   - readerio: Reader combined with IO effects
//   - readereither: Reader combined with Either for error handling
//   - readerioeither: Reader combined with IO and Either
package reader

//go:generate go run .. reader --count 10 --filename gen.go
